package com.qf.mybatisplus.utils;

import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

public class ToolUtil {

	public static final Logger LOGGER = LoggerFactory.getLogger(ToolUtil.class);


	/**
	 *
	 * @param paramStr 输入需要加密的字符串
	 * @return
	 */
	public static String entryptPassword(String paramStr,String salt) {
		if(StringUtils.isNotEmpty(paramStr)){
			byte[] saltStr = Encodes.decodeHex(salt);
			byte[] hashPassword = Digests.sha1(paramStr.getBytes(), saltStr, Constants.HASH_INTERATIONS);
			String password = Encodes.encodeHex(hashPassword);
			return password;
		}else{
			return null;
		}

	}

	/**
	 * 获取客户端的ip信息
	 * 
	 * @param request
	 * @return
	 */
	public static String getClientIp(HttpServletRequest request) {
		String ip = request.getHeader("X-Real-IP");
		LOGGER.info("ipadd : " + ip);
		if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("X-Forwarded-For");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknow".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		LOGGER.info(" ip --> " + ip);
		return ip;
	}
	
	/**
     * 将bean转换成map
     * @param condition
     * @return
     */
    @SuppressWarnings("unchecked")
	public static Map<String, Object> convertBeanToMap(Object condition) {
		if (condition == null) {
			return null;
		}
		if (condition instanceof Map) {
			return (Map<String, Object>) condition;
		}
		Map<String, Object> objectAsMap = new HashMap<String, Object>();
		BeanInfo info = null;
		try {
			info = Introspector.getBeanInfo(condition.getClass());
		} catch (IntrospectionException e) {
			e.printStackTrace();
		}

		for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
			Method reader = pd.getReadMethod();
			if (reader != null&&!"class".equals(pd.getName())) {
                try {
                    objectAsMap.put(pd.getName(), reader.invoke(condition));
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
		}
		return objectAsMap;
	}

	/**

	 * 通过文件名判断并获取OSS服务文件上传时文件的contentType

	 * @param fileName 文件名

	 * @return 文件的contentType

	 */
	public static  String getContentType(String fileName){
		int d = fileName.lastIndexOf(".");
		if( d== -1){
			return "text/html";
		}
		String fileExtension = fileName.substring(fileName.lastIndexOf("."));
		if(".bmp".equalsIgnoreCase(fileExtension)) {
            return "image/bmp";
        }
		if(".gif".equalsIgnoreCase(fileExtension)) {
            return "image/gif";
        }
		if(".jpeg".equalsIgnoreCase(fileExtension) || ".jpg".equalsIgnoreCase(fileExtension)) {
            return "image/jpeg";
        }
		if(".png".equalsIgnoreCase(fileExtension)) {
            return "image/png";
        }
		if(".html".equalsIgnoreCase(fileExtension)) {
            return "text/html";
        }
		if(".txt".equalsIgnoreCase(fileExtension)) {
            return "text/plain";
        }
		if(".vsd".equalsIgnoreCase(fileExtension)) {
            return "application/vnd.visio";
        }
		if(".ppt".equalsIgnoreCase(fileExtension) || ".pptx".equalsIgnoreCase(fileExtension)) {
            return "application/vnd.ms-powerpoint";
        }
		if(".doc".equalsIgnoreCase(fileExtension) || ".docx".equalsIgnoreCase(fileExtension)) {
            return "application/msword";
        }
		if(".xml".equalsIgnoreCase(fileExtension)) {
            return "text/xml";
        }
		if((".mp4").equalsIgnoreCase(fileExtension)) {
            return "video/mp4";
        }
		return "text/html";
	}

	/**
	 * 判断请求是否是ajax请求
	 * @param request
	 * @return
	 */
	public static boolean isAjax(HttpServletRequest request){
		String accept = request.getHeader("accept");
        return accept != null && accept.contains("application/json") || (request.getHeader("X-Requested-With") != null && request.getHeader("X-Requested-With").contains("XMLHttpRequest"));
    }

	/**
	 * 获取操作系统,浏览器及浏览器版本信息
	 * @param request
	 * @return
	 */
	public static Map<String,String> getOsAndBrowserInfo(HttpServletRequest request){
		Map<String,String> map = new HashMap<>();
		String  browserDetails  =   request.getHeader("User-Agent");
		String  userAgent       =   browserDetails;
		String  user            =   userAgent.toLowerCase();

		String os = "";
		String browser = "";

		//=================OS Info=======================
		if (userAgent.toLowerCase().contains("windows"))
		{
			os = "Windows";
		} else if(userAgent.toLowerCase().contains("mac"))
		{
			os = "Mac";
		} else if(userAgent.toLowerCase().contains("x11"))
		{
			os = "Unix";
		} else if(userAgent.toLowerCase().contains("android"))
		{
			os = "Android";
		} else if(userAgent.toLowerCase().contains("iphone"))
		{
			os = "IPhone";
		}else{
			os = "UnKnown, More-Info: "+userAgent;
		}
		//===============Browser===========================
		if (user.contains("edge"))
		{
			browser=(userAgent.substring(userAgent.indexOf("Edge")).split(" ")[0]).replace("/", "-");
		} else if (user.contains("msie"))
		{
			String substring=userAgent.substring(userAgent.indexOf("MSIE")).split(";")[0];
			browser=substring.split(" ")[0].replace("MSIE", "IE")+"-"+substring.split(" ")[1];
		} else if (user.contains("safari") && user.contains("version"))
		{
			browser=(userAgent.substring(userAgent.indexOf("Safari")).split(" ")[0]).split("/")[0]
					+ "-" +(userAgent.substring(userAgent.indexOf("Version")).split(" ")[0]).split("/")[1];
		} else if ( user.contains("opr") || user.contains("opera"))
		{
			if(user.contains("opera")){
				browser=(userAgent.substring(userAgent.indexOf("Opera")).split(" ")[0]).split("/")[0]
						+"-"+(userAgent.substring(userAgent.indexOf("Version")).split(" ")[0]).split("/")[1];
			}else if(user.contains("opr")){
				browser=((userAgent.substring(userAgent.indexOf("OPR")).split(" ")[0]).replace("/", "-"))
						.replace("OPR", "Opera");
			}

		} else if (user.contains("chrome"))
		{
			browser=(userAgent.substring(userAgent.indexOf("Chrome")).split(" ")[0]).replace("/", "-");
		} else if ((user.contains("mozilla/7.0")) || (user.contains("netscape6"))  ||
				(user.contains("mozilla/4.7")) || (user.contains("mozilla/4.78")) ||
				(user.contains("mozilla/4.08")) || (user.contains("mozilla/3")) )
		{
			browser = "Netscape-?";

		} else if (user.contains("firefox"))
		{
			browser=(userAgent.substring(userAgent.indexOf("Firefox")).split(" ")[0]).replace("/", "-");
		} else if(user.contains("rv"))
		{
			String IEVersion = (userAgent.substring(userAgent.indexOf("rv")).split(" ")[0]).replace("rv:", "-");
			browser="IE" + IEVersion.substring(0,IEVersion.length() - 1);
		} else
		{
			browser = "UnKnown, More-Info: "+userAgent;
		}
		map.put("os",os);
		map.put("browser",browser);
		return map;
	}
	
	/** 
     * 大陆手机号码11位数，匹配格式：前三位固定格式+后8位任意数 
     * 此方法中前三位格式有： 
     * 13+任意数 
     * 15+除4的任意数 
     * 18+除0和9的任意数 
     * 17+除9的任意数 
     * 147 
     */  
    public static boolean isPhoneLegal(String str) throws PatternSyntaxException {  
        String regExp = "^((13[0-9])|(15[^4])|(18[0-9])|(17[0-8])|(147))\\d{8}$";  
        Pattern p = Pattern.compile(regExp);  
        Matcher m = p.matcher(str);  
        return m.matches();  
    }
	
	/**
	 * 获取项目路径
	 * @return
	 */
    public static String getExportPath(String subDirPath){
	    // 获得项目的绝对路径 到 /classes
		String path = ToolUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath().toString();
		String filePath = "";
		// 分系统截取需要的路径
		if (System.getProperties().getProperty("os.name").startsWith("Windows")) {
			filePath = path.substring(path.indexOf("/") + 1,path.indexOf("/target"));
			if(subDirPath != null && !"".equals(subDirPath.trim())){
				filePath = filePath + "/"+subDirPath+"/";
			}
			filePath = filePath.replaceAll("/", "\\\\");
		} else {
			filePath = path.substring(0, path.indexOf("/target"));
			if(subDirPath != null && !"".equals(subDirPath.trim())){
				filePath = filePath + "/"+subDirPath+"/";
			}
		}	
		File file = new File(filePath);
		if(!file.exists()){
			file.mkdirs();
		}
	    return filePath;
    }
    
    /** 
     * 删除单个文件 
     * @param  filePath 被删除文件的文件名
     * @return 单个文件删除成功返回true，否则返回false 
     */  
    public static boolean deleteFile(String filePath) {  
        boolean flag = false;  
        File file = new File(filePath);  
        // 路径为文件且不为空则进行删除  
        if(file.isFile() && file.exists()) {  
            file.delete();  
            flag = true;  
        }  
        return flag;  
    }
    
    /** 
     * 删除目录（文件夹）以及目录下的文件 
     * @param   sPath 被删除目录的文件路径 
     * @return  目录删除成功返回true，否则返回false 
     */  
    public boolean deleteDirectory(String sPath) {  
		//如果sPath不以文件分隔符结尾，自动添加文件分隔符  
		if (!sPath.endsWith(File.separator)) {  
			sPath = sPath + File.separator;  
		}  
		File dirFile = new File(sPath);  
		//如果dir对应的文件不存在，或者不是一个目录，则退出  
		if (!dirFile.exists() || !dirFile.isDirectory()) {  
		    return false;  
		}
		
		boolean flag = true;  
		//删除文件夹下的所有文件(包括子目录)  
		File[] files = dirFile.listFiles();  
		for (int i = 0; i < files.length; i++) {  
		    if (files[i].isFile()) { //删除子文件  
		        flag = deleteFile(files[i].getAbsolutePath());  
		        if (!flag) {
                    break;
                }
		    } else { //删除子目录  
		        flag = deleteDirectory(files[i].getAbsolutePath());  
		        if (!flag) {
                    break;
                }
		    }  
		}  
		if (!flag) {
            return false;
        }
		//删除当前目录  
		if (dirFile.delete()) {  
		    return true;  
		} else {  
		    return false;  
		}  
    }
    
    /** 
     * 根据路径删除指定的目录或文件，无论存在与否 
     * @param sPath  要删除的目录或文件 
     * @return 删除成功返回 true，否则返回 false。 
     */  
    public boolean DeleteFolder(String sPath) {  
        boolean flag = false;  
        File file = new File(sPath);  
        //判断目录或文件是否存在  
        if (!file.exists()) { //不存在返回 false  
            return flag;  
        } else {  
            //判断是否为文件  
            if (file.isFile()) { //为文件时调用删除文件方法  
                return deleteFile(sPath);  
            } else { //为目录时调用删除目录方法  
                return deleteDirectory(sPath);  
            }  
        }  
    }
    
    /**
     * 比较日期大小,日期格式 yyyy-MM-dd
     * 
     * @param dateStr1
     * @param dateStr2 为空时，默认与当前日期比较
     * @return 
     * 	   -1:日期dateStr1 在 dateStr2 前面；
     * 		1:日期dateStr1 在 dateStr2 后面；
     * 		0:日期dateStr1 与 dateStr2 是同一天
     */
	public static int compareDate(String dateStr1, String dateStr2) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			Date date1 = sdf.parse(dateStr1);
			if(StringUtils.isBlank(dateStr2)){ //dateStr2为空时，默认与当前日期比较
				dateStr2 = sdf.format(new Date());
			}
			Date date2 = sdf.parse(dateStr2);
			if (date1.getTime() < date2.getTime()) {
				//System.out.println("日期dateStr1 在 dateStr2 前面");
				return -1;
			} else if (date1.getTime() > date2.getTime()) {
				//System.out.println("日期dateStr1 在 dateStr2 后面");
				return 1;
			} else {
				//System.out.println("日期dateStr1 与 dateStr2 是同一天");
				return 0;
			}
	     } catch (Exception exception) {
	         exception.printStackTrace();
	     }
	     return 0;
	}
	
	/**
	 * 对象属性转换为表字段  例如：userName to user_name
	 * @param property 对象属性名
	 * @return
	 */
	public static String propertyToField(String property) {
		if (null == property) {
			return "";
		}
		char[] chars = property.toCharArray();
		StringBuffer sb = new StringBuffer();
		for (char c : chars) {
			if (CharUtils.isAsciiAlphaUpper(c)) {
				sb.append("_" + StringUtils.lowerCase(CharUtils.toString(c)));
			} else {
				sb.append(c);
			}
		}
		return sb.toString();
	}
 
	/**
	 * 表字段转换成对象属性 例如：user_name to userName
	 * @param field 表字段
	 * @return
	 */
	public static String fieldToProperty(String field) {
		if (null == field) {
			return "";
		}
		char[] chars = field.toCharArray();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < chars.length; i++) {
			char c = chars[i];
			if (c == '_') {
				int j = i + 1;
				if (j < chars.length) {
					sb.append(StringUtils.upperCase(CharUtils.toString(chars[j])));
					i++;
				}
			} else {
				sb.append(c);
			}
		}
		return sb.toString();
	}
	
	public static String matchesPhoneNumber(String phoneNumber) {
		String sp = "";
		//移动号码校验正则
		Pattern p1 = Pattern.compile("(^((13[5-9])|147|(15[0|1|2|7|8|9])|178|(18[2|3|4|7|8])|198|148)\\d{8}$)|(^((134[0-8])|(170[3|5|6]))\\d{7}$)");
		//联通号码校验正则
		Pattern p2 = Pattern.compile("(^((13[0-2])|145|(15[5|6])|17[5|6]|(18[5|6])|171|166|146)\\d{8}$)|(^(170[4|7|8|9])\\d{7}$)");
		//电信号码校验正则
		Pattern p3 = Pattern.compile("(^(133|153|173|177|(18[0|1|9])|199|174)\\d{8}$)|(^(1349|(170[0-2]))\\d{7}$)");
		if (p1.matcher(phoneNumber).matches()) {
			sp = "cmcc";
		} else if (p3.matcher(phoneNumber).matches()) {
			sp = "ctcc";
		} else if (p2.matcher(phoneNumber).matches()) {
			sp = "cucc";
		}
        return sp;
	}
	
    public static void main(String[] args) {
//    	int compareRes = compareDate("2019-06-05",null);
//    	System.out.println(compareRes);
    	
    	// "joinGroupTime" --> "join_group_time"
    	String property = "joinGroupTime";
    	System.out.println("property:"+property);
    	String field = propertyToField(property);
    	System.out.println("field:"+field);
    	
    	// "user_name" --> "userName"
    	field = "user_name";
    	System.out.println("field:"+field);
    	property = fieldToProperty(field);
    	System.out.println("property:"+property);
	}
    
}
